<!DOCTYPE html>

<html>
    <head>
        <title>apply</title>
        <style scoped>
            body {
                width: 100%;
                height: 100%;
                margin: 0;
            }

            .box {
                background-color: violet;
                padding: 30px;
            }
        </style>
    </head>

    <body>
        <div class="box">改变函数运行时this指向，区别在于传参方式和执行时机两个方面</div>
    </body>

    <script>
        /** apply: fn.apply参数是数组，立即执行 **/
        let animal = {
            name: '动物',
            sing: function (song) {
                console.log(`${this.name}的叫声是${song}`)
            }
        }

        let dog = {
            name: '小狗'
        }

        let cat = {
            name: '小猫'
        }

        animal.sing.apply(dog, ['汪汪汪'])
        animal.sing.apply(cat, ['喵喵喵'])


        /** call：fn.call 参数是列表形式挨个传参，立即执行 **/
        let obj1 = {
            name: 'susan',
            sayHi: function () {
                console.log(`hello ${this.name}`)
            },
            print: function (val) {
                console.log('--打印--', val, '--剩余参数--', [...arguments])
            }
        }

        let obj2 = {
            name: 'lily'
        }

        obj1.sayHi.call(obj2)
        obj1.print.call(obj2, 'Hello World!', 10, 'yield')


        /** bind： fn.bind() 返回一个新函数，不立即执行**/
        let father = {
            name: '小头爸爸',
            eat: function (fruit) {
                console.log(`${this.name}爱吃${fruit}`)
            },
            sleep: function () {
                console.log(this.name + '会睡觉')
            }
        }

        let son = {
            name: '大头儿子'
        }

        let sonEat = father.eat.bind(son, '火龙果')
        let sonSleep = father.sleep.bind(son)
        console.log(sonEat(), sonSleep())

        father.eat('老北京鸡肉卷')
  
    </script>
</html>